package com.miniserver.tql.database.impl;

import java.sql.Connection;
import java.util.concurrent.Future;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;

import com.miniserver.tql.database.Configuration;
import com.miniserver.tql.database.ConnectionPool;
import com.miniserver.tql.database.PoolStatus;
import com.miniserver.util.LogUtil;

/**
 * 
 * @author work
 * @see 目前DatabaseEngineBaseImpl是支持多线程并发的
 */
public class ConnectionPoolImpl implements ConnectionPool {
	protected LogUtil log = LogUtil.getLogUtil("ConnectionPoolImpl");
	protected String name;
	protected DataSource connectionPool;
	protected PoolStatus status = new PoolStatus();
	protected static long checkInteval = 3600 * 1000L;
	protected static long lastCheckTime = 0L;

	public ConnectionPoolImpl(String name) {
		this.name = name;
	}

	public ConnectionPoolImpl(String name, Configuration config) {
		this.name = name;
		if (config != null) {
			this.initConnectionPool(config);
		}
	}

	/**
	 * 获取数据库连接
	 */
	@Override
	public Connection getConnection() {
		Connection con = null;
		try {
			Future<Connection> future = connectionPool.getConnectionAsync();
			while (!future.isDone()) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException x) {
					Thread.currentThread().interrupt();
				}
			}
			con = future.get();
		} catch (Exception ex) {
			//ex.printStackTrace();
			System.out.println("获取数据库连接失败");
			log.error("获取数据库连接失败", ex);
		}
		//
		if (System.currentTimeMillis() > lastCheckTime + checkInteval) {
			this.status.setFailedCount(0);
			this.status.setLastestCount(0);
		}
		//
		if (con == null) {
			this.status.setFailedCount(this.status.getFailedCount() + 1);
			this.status.setLastestCount(this.status.getLastestCount() + 1);
		} else {
			this.status.setLastestCount(this.status.getLastestCount() + 1);
		}
		return con;
	}

	public String getUrl(Configuration config) {
		return config.getParamValue(this.name + ".url");
	}

	public String getDriverClassName(Configuration config) {
		return config.getParamValue(this.name + ".driver");
	}

	public String getUserName(Configuration config) {
		return config.getParamValue(this.name + ".userName");
	}

	public String getPassword(Configuration config) {
		return config.getParamValue(this.name + ".password");
	}

	/**
	 * 初始化连接池
	 */
	protected void initConnectionPool(Configuration config) {
		try {
			PoolProperties p = new PoolProperties();
			String url = this.getUrl(config);
			p.setUrl(url);
			p.setDriverClassName(this.getDriverClassName(config));
			p.setUsername(this.getUserName(config));
			p.setPassword(this.getPassword(config));
			p.setJmxEnabled(true);
			p.setTestWhileIdle(true);
			p.setTestOnConnect(true);
			p.setTestOnReturn(true);
			p.setTestOnBorrow(true);
			p.setValidationQuery("SELECT 1");
			p.setTestOnReturn(false);
			p.setValidationInterval(60000);
			p.setTimeBetweenEvictionRunsMillis(60000);
			p.setMaxActive(70);
			p.setMaxIdle(10);
			p.setInitialSize(2);
			p.setMaxWait(30000);
			p.setRemoveAbandonedTimeout(60);
			p.setMinEvictableIdleTimeMillis(60000);
			p.setMinIdle(2);
			p.setLogAbandoned(true);
			p.setRemoveAbandoned(true);
			p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
					+ "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
			connectionPool = new DataSource();
			connectionPool.setPoolProperties(p);
			lastCheckTime = System.currentTimeMillis();
		} catch (Exception ex) {
			log.error(
					this.getDriverClassName(config) + ":" + this.getUrl(config),
					ex);
		}
	}

	/**
	 * 关闭连接池
	 */
	public void shutdown() {
		if (connectionPool != null) {		
			connectionPool.close(true);
		}
	}

	@Override
	public String getName() {
		return this.name;
	}

	@Override
	public PoolStatus getStatus() {
		this.status.setMaxActive(connectionPool.getMaxActive());
		this.status.setCurActive(connectionPool.getActive());
		return this.status;
	}
}
